/* =============================================================
 * stepper.js v1.1.0
 * =============================================================
 * Original written by Ysy
 * =============================================================
 * Date 22/05/2020
 * ============================================================ */

(function (factory) {
    "use strict";
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else {
        factory(jQuery);
    }
}(function ($) {

    let Stepper = function (element, options) {
        this.options = $.extend({}, $.fn.stepper.defaults, options);
        this.$element = $(element);
        this.$add = $(this.options.add);
        this.$sub = $(this.options.sub);
        this.$num = $(this.options.num);
        this.afterChange = this.options.afterChange;
        this.render();
        this.listen();
    };

    Stepper.prototype = {

        constructor: Stepper,

        render: function () {
            this.$element.append(this.$sub);
            this.$element.append(this.$num);
            this.$element.append(this.$add);
            this.$num.val(this.options.value);
        },

        listen: function () {
            this.$add.on("click", $.proxy(this.add, this));
            this.$sub.on("click", $.proxy(this.sub, this));
            this.$num
                .on("keyup", $.proxy(this.zero, this))
                .on("keyup paste change", $.proxy(this.change, this));
        },

        change: function (e) {
            e.keyCode === this.options.keyCodes.up && this.add();
            e.keyCode === this.options.keyCodes.down && this.sub();
            this.afterChange(this.$num.val());
        },

        add: function () {
            this.cal(+1);
            this.afterChange(this.$num.val());
        },

        sub: function () {
            this.cal(-1);
            this.afterChange(this.$num.val());
        },

        zero: function () {
            this.cal(0);
        },

        cal: function (num) {
            let number = this.$num.val().replace(/[^\d]/g, "");// 非数字替换成空

            let bv = parseInt(number || this.options.min) + num;
            if (bv >= this.options.min && bv <= this.options.max) this.$num.val(bv);

            if (bv <= this.options.min) {
                this.$num.val(this.options.min);
                this.show(this.$sub, 0, "DisDe", "Decrease");
            } else {
                this.show(this.$sub, 1, "Decrease", "DisDe");
            }

            if (bv >= this.options.max) {
                this.$num.val(this.options.max);
            }
        },

        show: function (element, t, _class, _sclass) {
            if (t === 0) {
                $(element).addClass(_class).removeClass(_sclass).removeClass("Increase");
            } else if (t === 1) {
                $(element).addClass(_class).removeClass(_sclass);
            }
        },
    };

    let old = $.fn.stepper;

    $.fn.stepper = function (options) {
        return new Stepper(this, options);
    };

    $.fn.stepper.defaults = {
        value: 1,
        min: 1,
        max: 99,
        length: 3,
        add: "<a href='javascript:void(0)' class='Increase'><i>+</i></a>",
        sub: "<a href='javascript:void(0)' class='DisDe'><i>-</i></a>",
        num: "<input class='Amount' autocomplete='off'/>",
        keyCodes: {
            up: 32,
            down: 40,
        },
        afterChange: $.noop,
    };

    $.fn.stepper.Constructor = Stepper;

    $.fn.stepper.noConflict = function () {
        $.fn.stepper = old;
        return this;
    };
}));
